/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.jackrabbit.webdav;

import org.apache.jackrabbit.webdav.xml.DomUtil;
import org.apache.jackrabbit.webdav.xml.XmlSerializable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * <code>Status</code> encapsulating the 'status' present in multistatus
 * responses.
 */
public class Status implements DavConstants, XmlSerializable {

	private static Logger log = LoggerFactory.getLogger(Status.class);

	/**
	 * Parse the given status line and return a new <code>Status</code> object.
	 * 
	 * @param statusLine
	 * @return a new <code>Status</code>
	 */
	public static Status parse(String statusLine) {
		if (statusLine == null) {
			throw new IllegalArgumentException(
					"Unable to parse status line from null xml element.");
		}
		Status status;

		// code copied from org.apache.commons.httpclient.StatusLine
		int length = statusLine.length();
		int at = 0;
		int start = 0;
		try {
			while (Character.isWhitespace(statusLine.charAt(at))) {
				++at;
				++start;
			}
			if (!"HTTP".equals(statusLine.substring(at, at += 4))) {
				log.warn("Status-Line '" + statusLine
						+ "' does not start with HTTP");
			}
			// handle the HTTP-Version
			at = statusLine.indexOf(" ", at);
			if (at <= 0) {
				log.warn("Unable to parse HTTP-Version from the status line: '"
						+ statusLine + "'");
			}
			String version = (statusLine.substring(start, at)).toUpperCase();
			// advance through spaces
			while (statusLine.charAt(at) == ' ') {
				at++;
			}
			// handle the Status-Code
			int code;
			int to = statusLine.indexOf(" ", at);
			if (to < 0) {
				to = length;
			}
			try {
				code = Integer.parseInt(statusLine.substring(at, to));
			} catch (NumberFormatException e) {
				throw new IllegalArgumentException(
						"Unable to parse status code from status line: '"
								+ statusLine + "'");
			}
			// handle the Reason-Phrase
			String phrase = "";
			at = to + 1;
			if (at < length) {
				phrase = statusLine.substring(at).trim();
			}

			status = new Status(version, code, phrase);

		} catch (StringIndexOutOfBoundsException e) {
			throw new IllegalArgumentException("Status-Line '" + statusLine
					+ "' is not valid");
		}
		return status;
	}

	private final String version;
	private final int code;

	private final String phrase;

	public Status(int code) {
		version = "HTTP/1.1";
		this.code = code;
		phrase = DavException.getStatusPhrase(code);
	}

	public Status(String version, int code, String phrase) {
		this.version = version;
		this.code = code;
		this.phrase = phrase;
	}

	public int getStatusCode() {
		return code;
	}

	/**
	 * @see XmlSerializable#toXml(Document)
	 */
	public Element toXml(Document document) {
		String statusLine = version + " " + code + " " + phrase;
		Element e = DomUtil.createElement(document, XML_STATUS, NAMESPACE);
		DomUtil.setText(e, statusLine);
		return e;
	}
}